package jee.boot.module.authority.service;

import jee.boot.common.basic.CrudService;
import jee.boot.entity.auth.Account;
import jee.boot.entity.system.Filter;
import jee.boot.common.standard.AuthorityHandler;
import jee.boot.common.utils.StringUtils;
import jee.boot.data.permission.config.AuthInterceptorThreadContext;
import jee.boot.entity.auth.*;
import jee.boot.module.authority.dao.SbjAggrDao;
import jee.boot.module.authority.dao.UserDao;
import jee.boot.module.oauth2.service.AccountService;
import jee.boot.entity.auth.AuthConstant;
import jee.boot.oauth.config.handler.LoadUserOwnerData;
import jee.boot.entity.system.BasicSbj;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户
 */
@Service
public class UserService extends CrudService<UserDao, User> {
    @Autowired
    private SbjAggrDao sbjAggrDao;
    @Autowired
    private AccountService accountService;
    @Autowired
    private GroupService groupService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private AuthorityService authorityService;
    @Autowired(required = false)
    private LoadUserOwnerData loadUserOwnerData;

    public UserService() {
    }

    public User get(User entity) {
        entity = super.get(entity);
        getMany(entity);
        return entity;
    }

    /**
     * 补充一对多数据
     *
     * @param entity
     */
    public void getMany(User entity) {
        /**
         * DIC_AUTH_AuthSbjType_AST01	用户
         * DIC_AUTH_AuthSbjType_AST02	用户组
         * DIC_AUTH_AuthSbjType_AST03	角色
         * DIC_AUTH_AuthSbjType_AST99	其它
         */
        // 根据用户ID查询所有角色/组
        List<SbjAggr> list = super.getOneToMany(sbjAggrDao, entity, new SbjAggr(), "sbj");
        if (list.size() > 0) {
            // 设置组
            Group group = new Group();
            group.addFilter(new Filter("id", "in", getBasicObjIdListByType(AuthConstant.AUTH_SBJ_TYPE_GROUP, list)));
            entity.setGroupList(groupService.findList(group));
            // 设置角色
            Role role = new Role();
            role.addFilter(new Filter("id", "in", getBasicObjIdListByType(AuthConstant.AUTH_SBJ_TYPE_ROLE, list)));
            entity.setRoleList(roleService.findList(role));
        }
    }

    @Override
    public void save(User entity) {
        Account account = entity.getAccount();
        /**
         * 自动创建新的登录账户
         */
//        account.setEmail(entity.getEmail());
//        account.setPhone(entity.getPhone());
//        account.setName(entity.getName());
        accountService.save(account);
        //保存数据
        super.save(entity);
        List<SbjAggr> list = new ArrayList<>();
        // 保存所有的角色关联
        if (entity.getRoleList() != null) {
            for (BasicSbj role : entity.getRoleList()) {
                list.add(new SbjAggr(AuthConstant.AUTH_SBJ_TYPE_USER, entity, AuthConstant.AUTH_SBJ_TYPE_ROLE, role));
            }
        }
        // 保存所有的组关联
        if (entity.getGroupList() != null) {
            for (BasicSbj group : entity.getGroupList()) {
                list.add(new SbjAggr(AuthConstant.AUTH_SBJ_TYPE_USER, entity, AuthConstant.AUTH_SBJ_TYPE_GROUP, group));
            }
        }

        // 插入关联数据
        super.saveOneToMany(sbjAggrDao, entity, "sbj", list);

    }

    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, key = "#entity.account.entityKey")
    })
    @Override
    public void update(User entity) {
        Account account = entity.getAccount();
        /**
         * 自动更新登录账户
         */
//        account.setEmail(entity.getEmail());
//        account.setPhone(entity.getPhone());
//        account.setName(entity.getName());
        accountService.update(entity.getAccount());
        //更新数据
        super.update(entity);
        List<SbjAggr> list = new ArrayList<>();
        // 保存所有的角色关联
        if (entity.getRoleList() != null) {
            for (BasicSbj role : entity.getRoleList()) {
                list.add(new SbjAggr(AuthConstant.AUTH_SBJ_TYPE_USER, entity, AuthConstant.AUTH_SBJ_TYPE_ROLE, role));
            }
        }
        // 修改所有的组关联
        if (entity.getGroupList() != null) {
            for (BasicSbj group : entity.getGroupList()) {
                list.add(new SbjAggr(AuthConstant.AUTH_SBJ_TYPE_USER, entity, AuthConstant.AUTH_SBJ_TYPE_GROUP, group));
            }
        }
        // 修改关联数据
        super.updateOneToMany(sbjAggrDao, entity, new SbjAggr(), "sbj", list);
    }

    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, key = "#entity.account.entityKey")
    })
    @Override
    public void delete(User entity) {
        // 删除用户
        super.delete(entity);
        // 删除对应的登录账户
        if (StringUtils.isNotBlank(entity.getAccount().getId())) {
            accountService.delete(entity.getAccount());
        }
        // 删除与group,role的关联关系
        super.deleteOneToMany(sbjAggrDao, entity, new SbjAggr(), "sbj");
    }

    /**
     * 根据账户查找用户
     *
     * @param account
     * @return
     */
    public User findUserByAccount(Account account) {
        User user = new User();
        user.addFilter(new Filter("account.id", "=", account.getId()));
        List<User> list = findList(user);
        // 账户为关联到用户上,直接返回空用户
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 根据登录账户查询关联的用户的所有权限数据
     *
     * @param user
     * @return
     */
    @Cacheable(value = AuthorityHandler.USER_AUTHORITY_KEY, key = "#user.account.entityKey")
    public User authorization(User user) {
        // 查询个人授权信息时候,需要先关闭权限拦截器
        Boolean authPermission = AuthInterceptorThreadContext.isAuthPermission();
        AuthInterceptorThreadContext.disableAuthPermission();

        Account account = user.getAccount();
        //未指定登录账户,直接返回空用户
        if (account == null || StringUtils.isBlank(account.getId())) {
            return user;
        }
        User userdb = findUserByAccount(user.getAccount());
        // 账户为关联到用户上,直接返回空用户
        if (userdb == null) {
            return user;
        }
        // 我们这里只考虑一个账户被一个用户绑定的情况
        user = userdb;
        // 补充一对多数据
        getMany(user);
        // 取出所有角色
        List<Role> allRole = new ArrayList<>();
        allRole.addAll(user.getRoleList());
        user.getRoleSet().addAll(user.getRoleList());
        if (!user.getGroupList().isEmpty()) {
            for (Group group : user.getGroupList()) {
                groupService.getMany(group);
                allRole.addAll(group.getRoleList());
                // 添加所有角色
                user.getRoleSet().addAll(group.getRoleList());
            }
        }

        // 获取所有角色里的原子权限
        if (!allRole.isEmpty()) {
            for (Role role : allRole) {
                roleService.getMany(role);
                if (!role.getAuthorityList().isEmpty()) {
                    // 再取出所有的配置的权限客体
                    for (Authority authority : role.getAuthorityList()) {
                        authorityService.getMany(authority);
                        // 添加所有原子权限
                        user.addAuthorityPermission(authority);
                    }
                }
            }
        }
        if (!user.getAuthoritySet().isEmpty()) {
            for (Authority authority : user.getAuthoritySet()) {
                List<AuthEntity> resourceList = authority.getResourceList();
                // 添加所有的资源,给前端渲染菜单使用
                user.getResourceSet().addAll(resourceList.stream().map(d -> (Resource) d.getEntity()).collect(Collectors.toList()));
                List<Resource> requestList = user.getResourceSet().stream().filter(resource -> StringUtils.equals(resource.getType(), "request")).collect(Collectors.toList());
                // 添加所有的请求,给后端过滤使用
                for (Resource request : requestList) {
                    user.getRequestMap().put(request.getId(), request);
                }
            }
        }
        if(loadUserOwnerData!=null){
            // 加载owner数据
            loadUserOwnerData.loadOwner(user);
        }
        // 查询个人授权信息结束,需要还原到之前的状态
        AuthInterceptorThreadContext.setAuthPermission(authPermission);
        return user;
    }

    /**
     * 根据关联表的数据按类型取出所有的权限主体entity的id
     *
     * @param type
     * @param list
     * @return
     */
    private List<String> getBasicObjIdListByType(String type, List<SbjAggr> list) {
        return list.stream()
                .filter(d -> StringUtils.equals(type, d.getObjType()))
                .map(d -> d.getObj().getId())
                .collect(Collectors.toList());
    }

    /**
     * 注册
     *
     * @param entity
     */
    public void register(Account entity) {
    }
}